package com.hrt.datasender.datastorage.strategy;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.btcode.common.MyLog;
import com.btcode.log.ILog;
import com.btcode.reflect.AutoClassLoader;
import com.btcode.reflect.IClassFinder;
import com.btcode.reflect.IClassLoader;
import com.hrt.datasender.datadao.model.BcSendPlatformDataStrategyModel;
import com.hrt.datasender.datadao.model.BcSendPlatformModel;
import com.hrt.datasender.datadao.service.BcSendPlatformDataStrategyService;
import com.hrt.datasender.datadao.service.BcSendPlatformService;

public final class StrategyLoader {

    private String basePacket = "com.hrt.datasender.datastorage.strategy";

    private ILog log;

    private static volatile StrategyLoader instance;

    /**
     * 系统中配置的策略
     */
    private List<IStorageStrategy> loaderStrategy = new ArrayList<>();

    /**
     * 程序中存在的策略
     */
    private List<IStorageStrategy> existStrategys = new ArrayList<>();

    private HashMap<String, IStorageStrategy> strategyMap = new HashMap<>();

    private StrategyLoader() {
        log = MyLog.getInstance().getLogger(getClass().getName());
    }

    public static StrategyLoader getInstance() {
        if (instance == null) {
            synchronized (StrategyLoader.class) {
                if (instance == null) {
                    instance = new StrategyLoader();
                }
            }
        }
        return instance;
    }

    public IStorageStrategy getStrategyById(String strategyId)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {

        loadAndGetStrategy();

        if (strategyMap.isEmpty()) {
            return null;
        }

        IStorageStrategy strategy = strategyMap.get(strategyId);

        return strategy;
    }

    /**
     * 加载配置好的策略
     * 
     * @throws IOException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws ClassNotFoundException
     */
    public synchronized List<IStorageStrategy> loadAndGetStrategy()
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {

        if (loaderStrategy != null && loaderStrategy.size() > 0) {
            return loaderStrategy;
        }

        List<IStorageStrategy> strategys = new ArrayList<>();
        List<IStorageStrategy> existStrategys = getExistStrategy();

        Set<String> strategyIds = getPlatformStrategySet();

        for (String strategyId : strategyIds) {

            for (IStorageStrategy strategy : existStrategys) {

                if (strategy.getStrategyId().equals(strategyId)) {
                    strategys.add(strategy);
                    strategyMap.put(strategyId, strategy);
                    log.info("策略：" + basePacket + "." + strategyId + "已加载");
                }
            }
        }

        loaderStrategy = strategys;

        return strategys;
    }

    /**
     * 获取系统中存在的策略
     *
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public synchronized List<IStorageStrategy> getExistStrategy()
            throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {

        if (existStrategys != null && existStrategys.size() > 0) {
            return existStrategys;
        }

        IClassFinder strategyFinder = new StrategyClassFinder();
        IClassLoader calssLoader = new AutoClassLoader(strategyFinder);

        List<IStorageStrategy> strategyList = new ArrayList<>();
        List<Class<?>> strategyClasses = calssLoader.loadClass(getClass(), basePacket);

        for (Class<?> myClass : strategyClasses) {
            Object instance = myClass.newInstance();
            strategyList.add((IStorageStrategy) instance);
        }

        existStrategys = strategyList;

        return strategyList;
    }

    /**
     * 获取配置好的，平台策略id集合
     * 
     * @return
     */
    public Set<String> getPlatformStrategySet() {

        List<BcSendPlatformModel> platformModels = BcSendPlatformService.getInstance().getModelList();

        Set<String> platformSet = new HashSet<>();

        for (BcSendPlatformModel platform : platformModels) {

            String platformId = platform.getPlatformId();
            List<BcSendPlatformDataStrategyModel> strategys = BcSendPlatformDataStrategyService.getInstance()
                    .getList(platformId);

            for (BcSendPlatformDataStrategyModel strategy : strategys) {
                String strategyId = strategy.getStorageStrategyId();
                platformSet.add(strategyId);
            }

        }

        return platformSet;
    }
}
